#include "devicemanager.h"
#include "../utils/logger.h"
#include "../io/modbusmaster.h"
#include "../database/dbmanager.h"

DeviceManager::DeviceManager(SerialPortManager *portManager, QObject *parent)
    : QObject(parent), m_portManager(portManager), m_pollScheduler(nullptr), m_scanning(false), m_discoveryTimeout(500), m_discoveryCurrentIndex(0), m_onlineCheckTimeout(10)
{
    // 创建轮询调度器
    m_pollScheduler = new PollScheduler(m_portManager, this);

    // 连接批量更新信号（用于UI刷新优化）
    connect(m_pollScheduler, &PollScheduler::meterDataBatchUpdated,
            this, &DeviceManager::meterDataBatchUpdated);

    // 连接数据采样信号（用于数据存储）
    connect(m_pollScheduler, &PollScheduler::meterDataSampled,
            this, &DeviceManager::meterDataSampled);

    // 创建定时器
    m_discoveryTimer = new QTimer(this);
    m_discoveryTimer->setSingleShot(true);
    connect(m_discoveryTimer, &QTimer::timeout, this, &DeviceManager::performTopologyDiscovery);

    m_onlineMonitorTimer = new QTimer(this);
    connect(m_onlineMonitorTimer, &QTimer::timeout, this, &DeviceManager::checkOnlineStatus);

    Logger::instance()->log(LogLevel::Info, "DeviceManager: 设备管理器已初始化");
}

DeviceManager::~DeviceManager()
{
    stopPolling();
    stopTopologyDiscovery();
    stopOnlineMonitor();

    // 清理电表对象
    qDeleteAll(m_meters);
    m_meters.clear();

    Logger::instance()->log(LogLevel::Info, "DeviceManager: 设备管理器已销毁");
}

// 添加总线配置
bool DeviceManager::addBusConfig(const BusConfig &config)
{
    // 验证配置
    if (config.busId < 1 || config.busId > 3)
    {
        Logger::instance()->log(LogLevel::Error,
                                QString("DeviceManager: 无效的总线ID: %1").arg(config.busId));
        return false;
    }

    if (config.startSlaveId < 1 || config.endSlaveId > 120 || config.startSlaveId > config.endSlaveId)
    {
        Logger::instance()->log(LogLevel::Error,
                                QString("DeviceManager: 无效的站号范围: %1-%2")
                                    .arg(config.startSlaveId)
                                    .arg(config.endSlaveId));
        return false;
    }

    m_busConfigs.append(config);

    Logger::instance()->log(LogLevel::Info,
                            QString("DeviceManager: 添加总线配置 - %1 (%2), 站号: %3-%4")
                                .arg(config.busName)
                                .arg(config.portName)
                                .arg(config.startSlaveId)
                                .arg(config.endSlaveId));

    return true;
}

// 添加总线配置（QML友好）
bool DeviceManager::addBusConfigQml(int busId, const QString &busName, const QString &portName, int startSlaveId, int endSlaveId)
{
    BusConfig config;
    config.busId = busId;
    config.busName = busName;
    config.portName = portName;
    config.startSlaveId = startSlaveId;
    config.endSlaveId = endSlaveId;

    return addBusConfig(config);
}

// 清空所有总线配置
void DeviceManager::clearBusConfigs()
{
    // 先停止轮询和拓扑识别
    stopPolling();
    stopTopologyDiscovery();
    stopOnlineMonitor();

    // 清空总线配置
    m_busConfigs.clear();

    Logger::instance()->log(LogLevel::Info, "DeviceManager: 已清空所有总线配置");
}

// 创建电表对象
Meter *DeviceManager::createMeter(int meterId, int busId, const QString &busName)
{
    // 检查是否已存在
    if (m_meters.contains(meterId))
    {
        return m_meters[meterId];
    }

    // 创建电表名称和位置
    QString name = QString("%1-%2号表").arg(busName).arg(meterId);
    QString location = QString("%1").arg(busName);

    Meter *meter = new Meter(meterId, name, location, busId, this);

    // 连接信号
    connect(meter, &Meter::onlineChanged, this, &DeviceManager::onMeterOnlineChanged);

    m_meters[meterId] = meter;

    emit totalCountChanged();

    // 保存电表信息到数据库（重要！用于历史数据外键约束）
    MeterInfo info;
    info.meterId = meterId;
    info.name = name;
    info.location = location;
    info.busId = busId;
    info.enabled = true;
    info.createTime = QDateTime::currentDateTime();
    info.updateTime = QDateTime::currentDateTime();

    if (!DBManager::instance()->saveMeterInfo(info))
    {
        Logger::instance()->log(LogLevel::Warning,
                                QString("DeviceManager: 保存电表 %1 信息到数据库失败").arg(meterId));
    }

    Logger::instance()->log(LogLevel::Debug,
                            QString("DeviceManager: 创建电表 %1 (%2)").arg(meterId).arg(name));

    return meter;
}

// 启动自动拓扑识别
void DeviceManager::startTopologyDiscovery(int timeout)
{
    if (m_scanning)
    {
        Logger::instance()->log(LogLevel::Warning, "DeviceManager: 拓扑识别已在进行中");
        return;
    }

    if (m_busConfigs.isEmpty())
    {
        Logger::instance()->log(LogLevel::Error, "DeviceManager: 未配置总线，无法启动拓扑识别");
        return;
    }

    m_discoveryTimeout = timeout;
    m_discoveryCurrentIndex = 0;
    m_discoverySlaveIds.clear();

    // 收集所有需要扫描的站号
    for (const BusConfig &config : m_busConfigs)
    {
        for (int slaveId = config.startSlaveId; slaveId <= config.endSlaveId; ++slaveId)
        {
            m_discoverySlaveIds.append(slaveId);
        }
    }

    m_scanning = true;
    emit scanningChanged();
    emit topologyDiscoveryStarted();

    Logger::instance()->log(LogLevel::Info,
                            QString("DeviceManager: 开始拓扑识别，共需扫描 %1 个站号")
                                .arg(m_discoverySlaveIds.size()));

    // 启动扫描
    m_discoveryTimer->start(10);
}

// 停止拓扑识别
void DeviceManager::stopTopologyDiscovery()
{
    if (m_scanning)
    {
        m_discoveryTimer->stop();
        m_scanning = false;
        emit scanningChanged();

        Logger::instance()->log(LogLevel::Info, "DeviceManager: 拓扑识别已停止");
    }
}

// 执行拓扑识别
void DeviceManager::performTopologyDiscovery()
{
    if (m_discoveryCurrentIndex >= m_discoverySlaveIds.size())
    {
        // 扫描完成
        m_scanning = false;
        emit scanningChanged();

        int foundCount = 0;
        for (Meter *meter : m_meters)
        {
            if (meter->isOnline())
            {
                foundCount++;
            }
        }

        emit topologyDiscoveryCompleted(foundCount);

        Logger::instance()->log(LogLevel::Info,
                                QString("DeviceManager: 拓扑识别完成，发现 %1 块在线电表，共 %2 块电表")
                                    .arg(foundCount)
                                    .arg(m_meters.size()));
        return;
    }

    int slaveId = m_discoverySlaveIds[m_discoveryCurrentIndex];

    // 发送进度信号
    emit topologyDiscoveryProgress(m_discoveryCurrentIndex + 1, m_discoverySlaveIds.size());

    // 找到对应的总线配置
    BusConfig *targetConfig = nullptr;
    for (BusConfig &config : m_busConfigs)
    {
        if (slaveId >= config.startSlaveId && slaveId <= config.endSlaveId)
        {
            targetConfig = &config;
            break;
        }
    }

    if (!targetConfig)
    {
        Logger::instance()->log(LogLevel::Error,
                                QString("DeviceManager: 找不到站号 %1 的总线配置").arg(slaveId));
        m_discoveryCurrentIndex++;
        m_discoveryTimer->start(10);
        return;
    }

    // 创建电表对象（如果不存在）
    Meter *meter = createMeter(slaveId, targetConfig->busId, targetConfig->busName);

    // 获取串口
    QSerialPort *port = m_portManager->getPort(targetConfig->portName);
    if (!port)
    {
        Logger::instance()->log(LogLevel::Error,
                                QString("DeviceManager: 串口 %1 未打开").arg(targetConfig->portName));
        m_discoveryCurrentIndex++;
        m_discoveryTimer->start(10);
        return;
    }

    // 创建Modbus主站进行测试读取
    ModbusMaster modbusMaster(port);
    ModbusMaster::ModbusResponse response = modbusMaster.readMeterData(slaveId, m_discoveryTimeout);

    if (response.success)
    {
        // 设备在线，更新数据
        meter->updateFromRegisters(response.data);
        emit deviceDiscovered(slaveId);

        Logger::instance()->log(LogLevel::Info,
                                QString("DeviceManager: 发现设备 - 站号: %1, 名称: %2")
                                    .arg(slaveId)
                                    .arg(meter->name()));
    }
    else
    {
        // 设备离线
        meter->setOnline(false);

        Logger::instance()->log(LogLevel::Debug,
                                QString("DeviceManager: 站号 %1 无响应").arg(slaveId));
    }

    // 继续下一个
    m_discoveryCurrentIndex++;
    m_discoveryTimer->start(10);
}

// 启动轮询
bool DeviceManager::startPolling(int pollInterval)
{
    if (m_busConfigs.isEmpty())
    {
        Logger::instance()->log(LogLevel::Error, "DeviceManager: 未配置总线，无法启动轮询");
        return false;
    }

    // 先停止现有轮询
    stopPolling();

    // 为每条总线添加配置
    bool anySuccess = false;
    for (const BusConfig &config : m_busConfigs)
    {
        // 获取该总线上的电表列表
        QVector<Meter *> busMeters = getMetersByBus(config.busId);

        if (busMeters.isEmpty())
        {
            Logger::instance()->log(LogLevel::Warning,
                                    QString("DeviceManager: 总线 %1 (%2) 没有电表")
                                        .arg(config.busId)
                                        .arg(config.busName));
            continue;
        }

        // 添加到轮询调度器
        bool success = m_pollScheduler->addBus(config.busId, config.portName, busMeters);

        if (success)
        {
            anySuccess = true;
            Logger::instance()->log(LogLevel::Info,
                                    QString("DeviceManager: 总线 %1 (%2) 添加到轮询调度器，电表数量: %3")
                                        .arg(config.busId)
                                        .arg(config.busName)
                                        .arg(busMeters.size()));
        }
        else
        {
            Logger::instance()->log(LogLevel::Error,
                                    QString("DeviceManager: 总线 %1 (%2) 添加失败")
                                        .arg(config.busId)
                                        .arg(config.busName));
        }
    }

    if (!anySuccess)
    {
        Logger::instance()->log(LogLevel::Error, "DeviceManager: 没有总线成功添加到轮询调度器");
        return false;
    }

    // 注意：信号连接已在构造函数中完成，这里不需要重复连接

    // 设置轮询间隔并启动
    m_pollScheduler->setPollInterval(pollInterval);
    m_pollScheduler->startPolling();

    Logger::instance()->log(LogLevel::Info,
                            QString("DeviceManager: 轮询已启动，间隔: %1ms").arg(pollInterval));
    return true;
}

// 停止轮询
void DeviceManager::stopPolling()
{
    if (m_pollScheduler)
    {
        m_pollScheduler->stopPolling();
        Logger::instance()->log(LogLevel::Info, "DeviceManager: 轮询已停止");
    }
}

// 启动在线状态监测
void DeviceManager::startOnlineMonitor(int checkInterval, int timeoutSeconds)
{
    m_onlineCheckTimeout = timeoutSeconds;

    // DeviceManager在主线程，定时器也在主线程，直接启动即可
    m_onlineMonitorTimer->start(checkInterval);

    Logger::instance()->log(LogLevel::Info,
                            QString("DeviceManager: 在线状态监测已启动，检查间隔: %1ms, 超时时间: %2s")
                                .arg(checkInterval)
                                .arg(timeoutSeconds));
}

// 停止在线状态监测
void DeviceManager::stopOnlineMonitor()
{
    m_onlineMonitorTimer->stop();
    Logger::instance()->log(LogLevel::Info, "DeviceManager: 在线状态监测已停止");
}

// 将所有电表设置为离线状态
void DeviceManager::setAllMetersOffline()
{
    // 注意：不能在持有锁的情况下调用 setOnline()，因为会触发信号导致死锁
    // 因此先收集需要设置离线的电表，然后释放锁再设置

    QVector<Meter *> metersToSetOffline;

    {
        QMutexLocker locker(&m_metersMutex);
        for (Meter *meter : m_meters)
        {
            if (meter && meter->isOnline())
            {
                metersToSetOffline.append(meter);
            }
        }
    } // 锁在这里释放

    // 现在在没有锁的情况下设置离线状态
    for (Meter *meter : metersToSetOffline)
    {
        meter->setOnline(false);
    }

    if (!metersToSetOffline.isEmpty())
    {
        Logger::instance()->log(LogLevel::Info,
                                QString("DeviceManager: 已将 %1 块电表设置为离线状态").arg(metersToSetOffline.size()));
    }
}

// 检查在线状态
void DeviceManager::checkOnlineStatus()
{
    // 注意：不能在持有锁的情况下调用 setOnline()，因为会触发信号导致死锁
    // 因此先收集超时的电表，然后释放锁再设置

    QVector<Meter *> timedOutMeters;

    {
        QMutexLocker locker(&m_metersMutex);

        for (Meter *meter : m_meters)
        {
            // 空指针检查
            if (!meter)
            {
                continue;
            }

            // 跳过已经离线的电表
            if (!meter->isOnline())
            {
                continue;
            }

            // 检查是否超时
            if (meter->isTimeout(m_onlineCheckTimeout))
            {
                timedOutMeters.append(meter);
            }
        }
    } // 锁在这里释放

    // 现在在没有锁的情况下设置离线状态
    for (Meter *meter : timedOutMeters)
    {
        meter->setOnline(false);

        Logger::instance()->log(LogLevel::Warning,
                                QString("DeviceManager: 电表 %1 (%2) 超时离线")
                                    .arg(meter->meterId())
                                    .arg(meter->name()));
    }
}

// 处理电表上线/离线状态变化
void DeviceManager::onMeterOnlineChanged()
{
    Meter *meter = qobject_cast<Meter *>(sender());
    if (!meter)
    {
        return;
    }

    if (meter->isOnline())
    {
        emit deviceOnline(meter->meterId());
        Logger::instance()->log(LogLevel::Info,
                                QString("DeviceManager: 电表 %1 (%2) 上线")
                                    .arg(meter->meterId())
                                    .arg(meter->name()));
    }
    else
    {
        emit deviceOffline(meter->meterId());
        Logger::instance()->log(LogLevel::Warning,
                                QString("DeviceManager: 电表 %1 (%2) 离线")
                                    .arg(meter->meterId())
                                    .arg(meter->name()));
    }

    emit onlineCountChanged();
    emit offlineCountChanged();
}

// 获取所有电表
QVector<Meter *> DeviceManager::getAllMeters() const
{
    QMutexLocker locker(&m_metersMutex);
    return m_meters.values().toVector();
}

// 根据ID获取电表
Meter *DeviceManager::getMeter(int meterId) const
{
    QMutexLocker locker(&m_metersMutex);
    return m_meters.value(meterId, nullptr);
}

// 根据总线ID获取电表列表
QVector<Meter *> DeviceManager::getMetersByBus(int busId) const
{
    QMutexLocker locker(&m_metersMutex);
    QVector<Meter *> result;

    for (Meter *meter : m_meters)
    {
        if (meter->busId() == busId)
        {
            result.append(meter);
        }
    }

    return result;
}

// 获取在线电表列表
QVector<Meter *> DeviceManager::getOnlineMeters() const
{
    QMutexLocker locker(&m_metersMutex);
    QVector<Meter *> result;

    for (Meter *meter : m_meters)
    {
        if (meter && meter->isOnline())
        {
            result.append(meter);
        }
    }

    return result;
}

// 获取在线电表数量
int DeviceManager::onlineCount() const
{
    QMutexLocker locker(&m_metersMutex);
    int count = 0;

    for (Meter *meter : m_meters)
    {
        if (meter && meter->isOnline())
        {
            count++;
        }
    }

    return count;
}

// 获取离线电表数量
int DeviceManager::offlineCount() const
{
    QMutexLocker locker(&m_metersMutex);
    int count = 0;

    for (Meter *meter : m_meters)
    {
        if (meter && !meter->isOnline())
        {
            count++;
        }
    }

    return count;
}

// 获取指定总线的在线电表数量
int DeviceManager::getOnlineCountByBus(int busId) const
{
    QMutexLocker locker(&m_metersMutex);
    int count = 0;

    for (Meter *meter : m_meters)
    {
        if (meter && meter->busId() == busId && meter->isOnline())
        {
            count++;
        }
    }

    return count;
}

// 获取指定总线的总功率
double DeviceManager::getTotalPowerByBus(int busId) const
{
    QMutexLocker locker(&m_metersMutex);
    double totalPower = 0.0;

    for (Meter *meter : m_meters)
    {
        if (meter && meter->busId() == busId && meter->isOnline())
        {
            totalPower += meter->totalPower();
        }
    }

    return totalPower;
}

// 获取指定总线的总电流
double DeviceManager::getTotalCurrentByBus(int busId) const
{
    QMutexLocker locker(&m_metersMutex);
    double totalCurrent = 0.0;

    for (Meter *meter : m_meters)
    {
        if (meter && meter->busId() == busId && meter->isOnline())
        {
            totalCurrent += meter->averageCurrent();
        }
    }

    return totalCurrent;
}